import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * create by cbb on 2018/4/8
 */
@Slf4j
public class TermOffset {
    public static final String HIGHLIGHT_PREV = "<em>";

    public static final String HIGHLIGHT_END = "</em>";


    private int start;
    private int end;
    private String token;

    public TermOffset(int start, int end, String token) {
        super();
        this.start = start;
        this.end = end;
        this.token = token;
    }

    public int getStart() {
        return start;
    }

    public void setStart(int start) {
        this.start = start;
    }

    public int getEnd() {
        return end;
    }

    public void setEnd(int end) {
        this.end = end;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public static boolean contains(List<TermOffset> offsets, int start, int end) {
        for (TermOffset offset : offsets) {
            if (offset.getStart() <= start && end <= offset.getEnd()) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        System.out.println(TermOffset.hlight("开心的不要不要的", Arrays.asList("开", "开心"), "开开心"));
//        System.out.println(TermOffset.hlight("据，构建了动态面板数据模型进行检验，得到主要结论如下：第一，在对中国产业集聚进行测度过程中，全面考量了中国产业集聚的总量水平及结构特征的演变情况，发现中国集聚密度整体呈现下降趋势，其中东部发达地区呈现下降幅度，但中西部欠发达地区呈现上升幅度。同时，说明中国产业集聚发展呈现阶梯状地区差异，较之东部发达地区的产业集聚发展，中西部欠发达地区的产业集聚发展存在时滞性，从而造成东中西部地区的产业集聚在全生命周期中，" +
//                "存在劳动力、资本等生产要素的空间配置异质性。", Arrays.asList("的"), "拒不执行判决裁定罪的法律适用问题"));
//        System.out.println(TermOffset.hlight("Z 公司人力资源管理系统设计与构建", Arrays.asList("项目", "风险", "管理"), "项目风险管理"));
//        String str = "开心的不要不要的";
//        str.indexOf()
    }

    /**
     * 高亮
     *
     * @param str   待高亮str
     * @param terms 高亮str集合
     * @return 高亮后的str
     */
    public static String hlight(String str, List<String> terms, String q) {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        if (terms == null || terms.size() < 1) {
            return str;
        }

        try {
            Pattern p = Pattern.compile(CharacterHelper.escapeExprSpecialWord(q.trim()), Pattern.CASE_INSENSITIVE);
            Matcher m = p.matcher(str);
            StringBuffer sb = new StringBuffer();
            while (m.find()) {
                m.appendReplacement(sb, HIGHLIGHT_PREV + m.group(0) + HIGHLIGHT_END);
            }
            m.appendTail(sb);
            String hlightStr = sb.toString();
            if (hlightStr.length() != str.length()) {
                return hlightStr;
            }
        } catch (Exception e) {
            log.error("highlight str:{} for q:{} failed,terms:{}", str, q, terms, e);
        }


        int highlightTagLen = HIGHLIGHT_END.length() + HIGHLIGHT_PREV.length();
        StringBuilder highlightTitle = new StringBuilder(str);
        str = str.toLowerCase();
        List<TermOffset> titleOffsets = new ArrayList<>();
        for (String _term : terms) {
            if (StringUtils.isBlank(_term)) {
                continue;
            }
            _term = _term.trim();
            _term = _term.toLowerCase();
//            System.out.println(_term);
            if (_term.length() == 0) {
                continue;
            }
            int index = -_term.length();
            int count = 0;
            while (str.indexOf(_term, index + _term.length()) != -1) {
                index = str.indexOf(_term, index + _term.length());
                count++;
                if (count == 10000) {
                    log.error("hlight error,term:" + _term + ",index:" + index + ",str:" + str + ",terms:" + terms);
                }
                if (!TermOffset.contains(titleOffsets, index, index + _term.length())) {
                    titleOffsets.add(new TermOffset(index, index + _term.length(), highlightTitle.substring(index, index + _term.length())));
                }
            }
        }

        // 如果有重合的就合并
        List<TermOffset> offsets = new ArrayList<>();
        titleOffsets.sort(Comparator.comparingInt(TermOffset::getStart));
        if (titleOffsets.size() > 1) {
            for (int i = 0; i < titleOffsets.size(); i++) {
                TermOffset offset = titleOffsets.get(i);
                if (i < titleOffsets.size() - 1) {
                    TermOffset nextOffset = titleOffsets.get(i + 1);
                    if (offset.getStart() < nextOffset.getStart() || offset.getEnd() > nextOffset.getEnd()) {
                        offsets.add(offset);
                    }
                } else {
                    offsets.add(offset);
                }
            }
            titleOffsets = offsets;
        }

        for (int i = 0; i < titleOffsets.size(); i++) {
            TermOffset offset = titleOffsets.get(i);
            highlightTitle.replace(offset.getStart() + i * highlightTagLen, offset.getEnd() + i * highlightTagLen, HIGHLIGHT_PREV + offset.getToken() + HIGHLIGHT_END);
        }
        String string = highlightTitle.toString();
        if (StringUtils.isBlank(string)) {
            return str;
        }
        return string;
    }

    /**
     * \S匹配任意的单个字符,将其替换成原来的,也就是做了一个去掉单字的操作
     *
     * @param str 输入字符串
     * @return 替换后的字符串
     */
    private static String hlightFilter(String str) {
//        System.out.println(str);
        String pattern = HIGHLIGHT_END + "(\\s*)" + HIGHLIGHT_PREV;
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(str);
        while (m.find()) {
            str = str.replaceFirst(pattern, m.group(1));
        }
        pattern = HIGHLIGHT_PREV + "(\\S)" + HIGHLIGHT_END;
        r = Pattern.compile(pattern);
        m = r.matcher(str);
        while (m.find()) {
            str = str.replaceFirst(pattern, m.group(1));
        }
        return str;
    }

    public static void high(List<String> values, List<String> terms) {
        if (terms == null || terms.isEmpty() || values == null || values.isEmpty()) {
            return;
        }
        Iterator<String> iter = values.iterator();
        List<String> high = new ArrayList<>();
        while (iter.hasNext()) {
            String val = iter.next();
            if (terms.contains(val.toLowerCase())) {
                iter.remove();
                high.add(TermOffset.HIGHLIGHT_PREV + val + TermOffset.HIGHLIGHT_END);//高亮的放到顶端
            }
        }
        high.forEach(val -> values.add(0, val));
    }
}

